# encoding:utf-8
'''
package manager base for plugin|runner
'''
import os
import sys
import re
from ccpm.collogger import Log
import subprocess
from argparse import ArgumentParser
from ccpm.glan import Lan
from ccpm.constants import Constant
import json
from ccpm.conffac import PackConf, GConf
from ccpm.model.modelusr import ModelUsr
import hashlib
import shutil
import binascii


def is_packcfg_be_content(packf):
    packconf = json.load(open(packf, "r"))
    temp_pack = PackConf().get_require_conf()
    for pk, pval in temp_pack.items():
        if pk not in packconf:
            return (False, None)
    return (True, packconf)


def is_ver_be_content(strver):
    strver = strver.split("-")
    ver_num = strver[0]
    is_vernum = re.match(r"^v\d{1,2}.\d{1,2}.\d{1,2}$", ver_num)
    is_verdec = False
    if len(strver) > 1:
        ver_dec = strver[1]
        is_verdec = re.match(r"^(%s)\d{1,2}$" %
                             "|".join(Constant.VER_SEMANTIC), ver_dec)
        return is_verdec and is_vernum
    return is_vernum


def is_pname_be_content(strname):
    return True


class PmUtil:
    @staticmethod
    def path_compatible(tpath):
        """ 路径平台兼容 """
        return tpath.replace("/", os.sep)

    @staticmethod
    def get_file_md5(tfile):
        """ 获取文件md5 """
        m5 = hashlib.md5()
        data = open(tfile, "rb")
        while True:
            b = data.read(1024)
            if not b:
                break
            m5.update(b)
        data.close()
        return m5.hexdigest()

    @staticmethod
    def is_package_projpath(tpath):
        conff = os.path.join(os.getcwd(), Constant.PACKINFO_FILE)
        if not os.path.isfile(conff):
            return (False, None)
        (issuc, packf) = is_packcfg_be_content(conff)
        return (issuc, packf)

    @staticmethod
    def refresh_packinfo(tpath, dic):
        conff = os.path.join(tpath, Constant.PACKINFO_FILE)
        if not os.path.isfile(conff):
            return (False, None)
        (issuc, packf) = is_packcfg_be_content(conff)
        if (issuc):
            packf.update(dic)
            with open(conff, "w") as fp:
                fp.write(json.dumps(packf, sort_keys=True, indent=4))

    @staticmethod
    def is_packcfg_fmtright(diccfg):
        pver = diccfg.get("ver")
        pname = diccfg.get("name")
        return is_pname_be_content(pname) and is_ver_be_content(pver)

    @staticmethod
    def is_runable_package_projpath(tpath):
        (issuc, packf) = PmUtil.is_package_projpath(tpath)
        if (issuc):
            if PmUtil.is_packcfg_fmtright(packf):
                if "scripts" in packf:
                    return (issuc, packf)
        return (False, None)

    @staticmethod
    def get_plugin_name(pstr):
        return pstr.split("@")[0]

    @staticmethod
    def chk_usr_enable():
        authtype = GConf().get("auth_type")
        Log().info("chking usr by type <%s>...", authtype)
        issuc = ModelUsr().chk_usrinfo(authtype)
        return issuc

    @staticmethod
    def is_namever_be_content(strnv):
        ilist = strnv.split("@")
        if len(ilist) > 1:
            return is_pname_be_content(ilist[0]) and\
                is_ver_be_content(ilist[1])


class CmdRunner:
    @staticmethod
    def run_cmd(strcmd, isquite=False, cwd=os.getcwd()):
        sys.stdout.flush()
        ret = subprocess.call(strcmd, shell=True, cwd=cwd)
        if isquite:
            if ret != 0:
                Lan.g("ERR_RUNCMD")
            else:
                Log().info(ret)


class ExecuteError(ValueError):
    def __init__(self, msg):
        errmsg = msg
        ValueError.__init__(self, errmsg)


class PluginBase:
    PARSE_VAR_NAME = [
        "is_hookfunc"
    ]
    name = ""
    _info = dict()  # tools-bin baseinfo
    logger = None

    def __init__(self, plugininfo):
        self.logger = Log()
        if self.__chk_info(plugininfo):
            self._info = plugininfo
            self.name = self._info["name"]  # for convenience to get lan
        else:
            Log().error(Lan.g("ERR_PLUGININIT"))
            sys.exit(1)
        self._rm_tmplist = []

    def __chk_info(self, pinfo):
        TEMPLATE = dict(
            name=str,
            help=str
        )
        for k, v in TEMPLATE.items():
            if (k not in pinfo.keys()):
                return False
            if not isinstance(pinfo.get(k), v):
                return False
        return True

    def params_var(self, varname):
        if varname not in self.PARSE_VAR_NAME:
            return
        return self.get_info("name") + "_" + varname

    def rm_temp(self):
        for tf in self._rm_tmplist:
            if os.path.isdir(tf):
                shutil.rmtree(tf)
            elif os.path.isfile(tf):
                os.remove(tf)
            else:
                Log().warning("Unknow tar in <temp file list> to remove")
        self._rm_tmplist = []

    def append_rm_tmp(self, tar):
        self._rm_tmplist.append(tar)

    def get_info(self, infok):
        return self._info.get(infok)

    def print_help(self):
        strhelp = self.get_info("help")
        Log().info(strhelp)

    def parser_config(self, subparser):
        subparser.add_argument(
            "-plugin",
            dest=self.get_info("name"),
            help=Lan.p(self.get_info("name"), "INPUT_PLUGIN_NAME"),
            default=True
        )
        subparser.add_argument(
            "-ignore_hookfunc",
            dest=self.params_var("is_hookfunc"),
            help=Lan.p(self.get_info("name"), "IGNORE_HOOK_FUNC"),
            default=False
        )
        pass

    def is_ignorehook(self):
        return hasattr(self, self.params_var("is_hookfunc"))

    def run(self, argpars):
        pass

    def try_run(self, argpars):
        try:
            self.run(argpars)
        except ExecuteError as exerr:
            self.rm_temp()
            Log().error(exerr)
        self.rm_temp()

    def err_break(self, errlan):
        raise ExecuteError(errlan)


if __name__ == "__main__":
    pass
